/*******************************************************************************
* File Name    : ymodem.c
* Description  : mbootload的ymodem协议相关文件
* Data         : 2019-08-02  Friday
* Author       :
*******************************************************************************/
#include "ymodem.h"
#include "string.h"
#include "mainwindow.h"
/*********************************data*****************************************/
//文件名
ALIGN(4) unsigned char g_file_name[FILE_NAME_LENGTH];
//包缓存
#if MBL_USE_YMODEM_SEND
ALIGN(4) static unsigned char packet_d[PACKET_1K_SIZE + PACKET_OVERHEAD + 1];
static unsigned char *packet_data = packet_d+1;
#endif
/**
* @brief   整形数据转到字符串
* @param  n: 数据
*         buf：转换为的字符串,防止buf溢出！
* @retval None.
*/
void mitoa(int n, char buf[])
{
  int f_i = n;
  int div = 10000000;
  int state=0;
  int j=0;
  if(f_i>div)
      while(1);
  if(f_i<0)
  {
    buf[j++] = '-';
    f_i = 0-f_i;
  }
  for (;div>=10;div/=10)
  {
    buf[j++] = f_i/div+48;
    f_i%=div;
    if((buf[j-1]=='0')&&(state==0))
          j=j-1; else
          state = 1;
    if(div==10)
    {
      buf[j]=f_i+48;
      buf[j+1]='\0';
    }
  }
}
/**
* @brief  字符串转到数据
* @param  inputstr: 需转换的字符串
*         intnum：转好的数据
* @retval 1：正确
*         0：错误
*/
int matoi(unsigned char *inputstr, long *intnum)
{
  long i = 0, res = 0;
  long val = 0;
  if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X'))
  {
    if (inputstr[2] == '\0')
    {
      return 0;
    }
    for (i = 2; i < 11; i++)
    {
      if (inputstr[i] == '\0')
      {
        *intnum = val;
        //返回1
        res = 1;
        break;
      }
      if (ISVALIDHEX(inputstr[i]))
      {
        val = (val << 4) + CONVERTHEX(inputstr[i]);
      }
      else
      {
        //无效输入返回0
        res = 0;
        break;
      }
    }
    if (i >= 11)
    {
      res = 0;
    }
  }
  else //最多10为2输入
  {
    for (i = 0; i < 11; i++)
    {
      if (inputstr[i] == '\0')
      {
        *intnum = val;
        //返回1
        res = 1;
        break;
      }
      else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0))
      {
        val = val << 10;
        *intnum = val;
        res = 1;
        break;
      }
      else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0))
      {
        val = val << 20;
        *intnum = val;
        res = 1;
        break;
      }
      else if (ISVALIDDEC(inputstr[i]))
      {
        val = val * 10 + CONVERTDEC(inputstr[i]);
      }
      else
      {
        //无效输入返回0
        res = 0;
        break;
      }
    }
    //超过10位无效，返回0
    if (i >= 11)
    {
      res = 0;
    }
  }
  return res;
}
#if MBL_USE_YMODEM_SEND
/**
* @brief   从发送端接收一个数据包
* @param  data ：数据指针
*         length：长度
*         timeout ：超时时间
* @retval 0: 正常返回
*        -1: 超时或者数据包错误
*         1: 用户取消
*/
static long receive_packet(unsigned char *data, long *length, unsigned long timeout)
{
  unsigned int i, packet_size;
  unsigned char c=0;
  *length = 0;
  if (mbl_recv_byte(&c, timeout) != 0)
  {
    return -1;
  }
  switch (c)
  {
  case SOH:
    packet_size = PACKET_SIZE;
    break;
  case STX:
    packet_size = PACKET_1K_SIZE;
    break;
  case EOT:
    return 0;
  case CA:
    if ((mbl_recv_byte(&c, timeout) == 0) && (c == CA))
    {
      *length = -1;
      return 0;
    }
    else
    {
      return -1;
    }
  case ABORT1:
  case ABORT2:
    return 1;
  default:
    return -1;
  }
  *data = c;
  for (i = 1; i < (packet_size + PACKET_OVERHEAD); i++)
  {
    if (mbl_recv_byte(data + i, timeout) != 0)
    {
      return -1;
    }
  }
  if (data[PACKET_SEQNO_INDEX] != ((data[PACKET_SEQNO_COMP_INDEX] ^ 0xff) & 0xff))
  {
    return -1;
  }
  *length = packet_size;
  return 0;
}
/**
  * @brief   通过 ymodem协议接收一个文件
  * @param  buf: 首地址指针
  * @retval 文件长度
  */
long ymodem_receive(void)
{
  unsigned char file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
  long i, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;
  for (session_done = 0, errors = 0, session_begin = 0;;)
  {
    for (packets_received = 0, file_done = 0,buf_ptr=packet_data;;)
    {
      switch (receive_packet(packet_data, &packet_length, NAK_TIMEOUT))
      {
      case 0:
        errors = 0;
        switch (packet_length)
        {
        //发送端终止
        case -1:
          mbl_send_byte(ACK);
          return MBL_YMODEM_ABORTED_ERROR;
        //结束传输
        case 0:
          mbl_send_byte(ACK);
          file_done = 1;
          break;
          //正常的数据包
        default:
          if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
          {
            mbl_send_byte(NAK);
          }
          else
          {
            if (packets_received == 0)
            {
              //文件名数据包
              if (packet_data[PACKET_HEADER] != 0)
              {
                //文件名数据包有效数据区域
                for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);)
                {
                  g_file_name[i++] = *file_ptr++;
                }
                g_file_name[i++] = '\0';
                for (i = 0, file_ptr++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);)
                {
                  file_size[i++] = *file_ptr++;
                }
                file_size[i++] = '\0';
                matoi(file_size, &size);
                //处理接收到的包信息
                if(mbl_deal_pack_info(size) != 0)
                {
                  //结束
                  mbl_send_byte(CA);
                  mbl_send_byte(CA);
                  return -1;
                }
                else
                {
                  mbl_send_byte(ACK);
                  mbl_send_byte(CRC16);
                }
              }
              //文件名数据包空，结束传输
              else
              {
                mbl_send_byte(ACK);
                file_done = 1;
                session_done = 1;
                break;
              }
            }
            //数据包
            else
            {
              //RamSource = (unsigned long *)(buf_ptr+PACKET_HEADER);
              //把接收到的数据编写到Flash中
              //mbl_deal_pack_data();
//              if (mbl_flash_write_word(FlashDestination, RamSource,packet_length/4,MBL_APP_WR_ADR)<0)
//              {
//                //结束
//                mbl_send_byte(CA);
//                mbl_send_byte(CA);
//                return MBL_FLASH_WRITE_ERROR;
//              }
//              FlashDestination += packet_length;
              mbl_send_byte(ACK);
            }
            packets_received++;
            session_begin = 1;
          }
        }
        break;
      case 1:
        mbl_send_byte(CA);
        mbl_send_byte(CA);
        return MBL_YMODEM_ABORTED_USER;
      default:
        if (session_begin > 0)
        {
          errors++;
        }
        if (errors > MAX_ERRORS)
        {
          mbl_send_byte(CA);
          mbl_send_byte(CA);
          return 0;
        }
        mbl_send_byte(CRC16);
        break;
      }
      if (file_done != 0)
      {
        break;
      }
    }
    if (session_done != 0)
    {
      break;
    }
  }
  return (long)size;
}
#endif
/**
* @brief   通过 ymodem协议检测响应
* @param  c: 测试字符
* @retval none
*/
    /*
long Ymodem_CheckResponse(unsigned char c)
{
    return 0;
}
*/
/**
* @brief   准备第一个数据包
* @param  data：数据包
*         fileName ：文件名
*         length ：长度
* @retval none
*/

void Ymodem_PrepareIntialPacket(unsigned char *data, const unsigned char *fileName, unsigned long *length)
{
  unsigned int i, j;
  unsigned char file_ptr[10];
  //制作头3个数据包
  data[0] = SOH;
  data[1] = 0x00;
  data[2] = 0xff;
  //文件名数据包有效数据
  for (i = 0; (fileName[i] != '\0') && (i < FILE_NAME_LENGTH); i++)
  {
    data[i + PACKET_HEADER] = fileName[i];
  }
  data[i + PACKET_HEADER] = 0x00;
  mitoa(*length, (char *)file_ptr);
  for (j = 0, i = i + PACKET_HEADER + 1; file_ptr[j] != '\0';)
  {
    data[i++] = file_ptr[j++];
  }
  for (j = i; j < PACKET_SIZE + PACKET_HEADER; j++)
  {
    data[j] = 0;
  }
}

/**
  * @brief   准备数据包
  * @param  SourceBuf：数据源缓冲
  *         data：数据包
  *         pktNo ：数据包编号
  *         sizeBlk ：长度
  * @retval none
  */

void Ymodem_PreparePacket(unsigned char *SourceBuf, unsigned char *data, unsigned char pktNo, unsigned long sizeBlk)
{
    unsigned int i, size, packetSize;
    unsigned char *file_ptr;
    //制作头3个数据包
    packetSize = sizeBlk >= PACKET_1K_SIZE ? PACKET_1K_SIZE : PACKET_SIZE;
    size = sizeBlk < packetSize ? sizeBlk : packetSize;
    if (packetSize == PACKET_1K_SIZE)
    {
        data[0] = STX;
    }
    else
    {
        data[0] = SOH;
    }
    data[1] = pktNo;
    data[2] = (~pktNo);
    file_ptr = SourceBuf;
    //文件名数据包有效数据
    for (i = PACKET_HEADER; i < size + PACKET_HEADER; i++)
    {
        data[i] = *file_ptr++;
    }
    if (size <= packetSize)
    {
        for (i = size + PACKET_HEADER; i < packetSize + PACKET_HEADER; i++)
        {
            data[i] = 0x1A; //结束
        }
    }
}

/**
* @brief  更新输入数据的CRC校验
* @param  data ：数据
*         size ：长度
* @retval CRC校验值
*/
#define MBL_USE_CRC16
#define MBL_USE_CRC_CAL 1
#if defined(MBL_USE_CRC16)
#if MBL_USE_CRC_CAL
/**
  * @brief   更新输入数据的CRC校验
  * @param  crcIn：
  *         byte：
  * @retval CRC校验值
  */
unsigned int update_crc16(unsigned int crcIn, unsigned char byte)
{
    unsigned long crc = crcIn;
    unsigned long in = byte | 0x100;
    do
    {
            crc <<= 1;
            in <<= 1;
            if (in & 0x100)
                    ++crc;
            if (crc & 0x10000)
                    crc ^= 0x1021;
    } while (!(in & 0x10000));
    return crc & 0xffffu;
}

unsigned int Cal_CRC16(const unsigned char *data, unsigned long size)
{
    unsigned long crc = 0;
    const unsigned char *dataEnd = data + size;
    while (data < dataEnd)
        crc = update_crc16(crc, *data++);
    crc = update_crc16(crc, 0);
    crc = update_crc16(crc, 0);
    return crc & 0xffffu;
}
#elif MBL_USE_CRC_TAB
// The table for fast CRC16 calculation
static const uint8_t crc_hi[] = {
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
    0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
    0x41, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00,
    0xC1, 0x81, 0x40,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
    0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
    0x40, 0x01, 0xC0,
    0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
    0x80, 0x41, 0x01,
    0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
    0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
    0x00, 0xC1, 0x81,
    0x40
};
static const uint8_t crc_low[] = {
    0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
    0x05, 0xC5, 0xC4,
    0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB,
    0x0B, 0xC9, 0x09,
    0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
    0xDF, 0x1F, 0xDD,
    0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2,
    0x12, 0x13, 0xD3,
    0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
    0x36, 0xF6, 0xF7,
    0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E,
    0xFE, 0xFA, 0x3A,
    0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B,
    0x2A, 0xEA, 0xEE,
    0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27,
    0xE7, 0xE6, 0x26,
    0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
    0x63, 0xA3, 0xA2,
    0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD,
    0x6D, 0xAF, 0x6F,
    0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8,
    0xB9, 0x79, 0xBB,
    0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4,
    0x74, 0x75, 0xB5,
    0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
    0x50, 0x90, 0x91,
    0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94,
    0x54, 0x9C, 0x5C,
    0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59,
    0x58, 0x98, 0x88,
    0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D,
    0x4D, 0x4C, 0x8C,
    0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
    0x41, 0x81, 0x80,
    0x40
};
// Calculate buffer checksum using tables
// The checksum CRC16 algorithm is specific
// for Modbus standard and uses polynomial value = 0xA001
static uint16_t get_buffer_crc16( uint8_t * frame_ptr, uint16_t length )
{
    while( frame_ptr == NULL);
    uint8_t crc_hi_byte = 0xFF;
    uint8_t crc_low_byte = 0xFF;
    int index;
    while ( length-- )
    {
        index = crc_low_byte ^ *(frame_ptr++);
        crc_low_byte = crc_hi_byte ^ crc_hi[index];
        crc_hi_byte = crc_low[index];
    }
    return ((crc_hi_byte << 8) | crc_low_byte);
}
#endif
#endif
/**
  * @brief  计算YModem数据包的总大小
  * @param  data ：数据
  *         size ：长度
  * @retval 数据包的总大小
  */
unsigned char CalChecksum(const unsigned char *data, unsigned long size)
{
    unsigned long sum = 0;
    const unsigned char *dataEnd = data + size;
    while (data < dataEnd)
        sum += *data++;
    return sum & 0xffu;
}
/**
* @brief  通过ymodem协议传输一个数据包
* @param  data ：数据地址指针
*         length：长度
* @retval none
*/
void Ymodem_SendPacket(unsigned char *data, unsigned int length)
{
  unsigned int i;
  i = 0;
  while (i < length)
  {
    mbl_send_byte(data[i]);
    i++;
  }
}
/**
  * @brief  通过ymodem协议传输一个文件
  * @param  buf ：数据地址指针
  *         sendFileName ：文件名
  *         sizeFile：文件长度
  * @retval 0：成功
  */
unsigned char ymodem_transmit(unsigned char *buf, const unsigned char *sendFileName, unsigned long sizeFile)
{
  unsigned char packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD];
  unsigned char FileName[FILE_NAME_LENGTH];
  unsigned char *buf_ptr, tempCheckSum;
  unsigned int tempCRC, blkNumber;
  unsigned char receivedC[2], CRC16_F = 0, i;
  unsigned long errors, ackReceived, size = 0, pktSize;
  errors = 0;
  ackReceived = 0;
  for (i = 0; i < (FILE_NAME_LENGTH - 1); i++)
  {
    FileName[i] = sendFileName[i];
  }
  CRC16_F = 1;
  //准备第一个数据包
  Ymodem_PrepareIntialPacket(&packet_data[0], FileName, &sizeFile);
  do
  {
    //发送数据包
    Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
    //发送CRC校验
    if (CRC16_F)
    {
      tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
      mbl_send_byte(tempCRC >> 8);
      mbl_send_byte(tempCRC & 0xFF);
    }
    else
    {
      tempCheckSum = CalChecksum(&packet_data[3], PACKET_SIZE);
      mbl_send_byte(tempCheckSum);
    }
    //等待响应
    if (mbl_recv_byte(&receivedC[0], 10000) == 0)
    {
      if (receivedC[0] == ACK)
      {
        //数据包正确传输
        ackReceived = 1;
      }
    }
    else
    {
      errors++;
    }
  } while (!ackReceived && (errors < 0x0A));
  if (errors >= 0x0A)
  {
    return errors;
  }
  buf_ptr = buf;
  size = sizeFile;
  blkNumber = 0x01;
  //1024字节的数据包发送
  while (size)
  {
      //准备下一个数据包
      Ymodem_PreparePacket(buf_ptr, &packet_data[0], blkNumber, size);
      ackReceived = 0;
      receivedC[0] = 0;
      errors = 0;
      do
      {
        //发送下一个数据包
        if (size >= PACKET_1K_SIZE)
        {
          pktSize = PACKET_1K_SIZE;
        }
        else
        {
          pktSize = PACKET_SIZE;
        }
        Ymodem_SendPacket(packet_data, pktSize + PACKET_HEADER);
        //发送CRC校验
        if (CRC16_F)
        {
          tempCRC = Cal_CRC16(&packet_data[3], pktSize);
          mbl_send_byte(tempCRC >> 8);
          mbl_send_byte(tempCRC & 0xFF);
        }
        else
        {
          tempCheckSum = CalChecksum(&packet_data[3], pktSize);
          mbl_send_byte(tempCheckSum);
        }
        //等待响应
        if ((mbl_recv_byte(&receivedC[0], 10000) == 0) && (receivedC[0] == ACK))
        {
          ackReceived = 1;
          if (size > pktSize)
          {
            buf_ptr += pktSize;
            size -= pktSize;
            if (blkNumber == (sizeFile+2048 / 1024))
            {
                return 0xFF; //错误
            }
            else
            {
                blkNumber++;
            }
          }
          else
          {
            buf_ptr += pktSize;
            size = 0;
          }
        }
        else
        {
          errors++;
        }
    } while (!ackReceived && (errors < 0x0A));
    //如果没响应10次就返回错误
    if (errors >= 0x0A)
    {
      return errors;
    }
  }
  ackReceived = 0;
  receivedC[0] = 0x00;
  errors = 0;
  do
  {
    mbl_send_byte(EOT);
    //发送 (EOT);
    //等待回应
    if ((mbl_recv_byte(&receivedC[0], 10000) == 0) && receivedC[0] == ACK)
    {
      ackReceived = 1;
    }
    else
    {
      errors++;
    }
  } while (!ackReceived && (errors < 0x0A));
  if (errors >= 0x0A)
  {
    return errors;
  }
  //准备最后一个包
  ackReceived = 0;
  receivedC[0] = 0x00;
  errors = 0;
  packet_data[0] = SOH;
  packet_data[1] = 0;
  packet_data[2] = 0xFF;
  for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++)
  {
    packet_data[i] = 0x00;
  }
  do
  {
    //发送数据包
    Ymodem_SendPacket(packet_data, PACKET_SIZE + PACKET_HEADER);
    //发送CRC校验
    tempCRC = Cal_CRC16(&packet_data[3], PACKET_SIZE);
    mbl_send_byte(tempCRC >> 8);
    mbl_send_byte(tempCRC & 0xFF);
    //等待响应
    if (mbl_recv_byte(&receivedC[0], 10000) == 0)
    {
      if (receivedC[0] == ACK)
      {
        //包传输正确
        ackReceived = 1;
      }
    }
    else
    {
      errors++;
    }
  } while (!ackReceived && (errors < 0x0A));
  //如果没响应10次就返回错误
  if (errors >= 0x0A)
  {
    return errors;
  }
  do
  {
    mbl_send_byte(EOT);
    //发送 (EOT);
    //等待回应
    if ((mbl_recv_byte(&receivedC[0], 10000) == 0) && receivedC[0] == ACK)
    {
      ackReceived = 1;
    }
    else
    {
      errors++;
    }
  } while (!ackReceived && (errors < 0x0A));
  if (errors >= 0x0A)
  {
    return errors;
  }
  return 0; //文件传输成功
}
